﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="DeleteList.cs" company="Collaboris Ltd.">
//   Copyright (c) Collaboris Ltd. All rights Reserved.
// </copyright>
// <summary>
//   Creates a new SPWeb.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Collaboris.Saf.Actions.Wss.List
{
    using System;
    using System.Collections.Generic;

    using Entities;
    using Engine;

    using SharePoint.Wss.Attributes;
    using SharePoint.Wss.Lists;
    using Utils;

    [CollaborisClass(
        Title = "Delete List",
        ReleaseStatus = ReleaseStatus.Stable,
        DisableDocumentation = false,
        ContactAuthorEmail = "Support@Collaboris.co.uk",
        Summary = "Destroys (or recycles) a SharePoint list. Can also optionally delete data only." ,
        UndoImplemented = true,
        ClassGuid = "{156E17A5-A7BA-4e1f-8A48-1BC341A7C652}"
    )
    ]
    public class DeleteList : WSSActionBase<ListToDelete>
    {
        /// <summary>
        /// Deleted List Property Name
        /// </summary>
        public const string DeletedListPropName = "DeletedListGuid";

        /// <summary>
        /// The Undo will ... (TODO) - Recycle Bin ?
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="entity">The data entityList.</param>
        /// <returns></returns>
        protected override ProcessStatus UndoAction(SafContext context, ListToDelete entity)
        {
            this.Trace.TraceMethodStart("UndoAction");

            // ProcessStatus rstate = this.ProcessDeleteList(entity, ProcessMode.Undo, context);
            ProcessStatus rstate = this.ProcessUndo(context, entity);

            this.Trace.TraceMethodEnd("UndoAction");
            return rstate;
        }        
        
        /// <summary>
        /// If the specified List exists then it will be deleted.
        /// <see cref="WebInfo"/>
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="entity">The data entityList.</param>
        /// <returns></returns>
        protected override ProcessStatus DoAction(SafContext context, ListToDelete entity)
        {
            this.Trace.TraceMethodStart("DoAction");

            ProcessStatus rstate = this.ProcessDo(context, entity);

            //ProcessStatus rstate = this.ProcessDeleteList(entity, ProcessMode.Do, context);

            this.Trace.TraceMethodEnd("DoAction");
            return rstate;
        }

        private ProcessStatus ProcessUndo(SafContext context, ListToDelete entity)
        {
            if (entity.Destroy.Value)
            {
                this.Trace.TraceVerbose(
                        "This list {0} cannot be restored in this web {1} - it was originally deleted and not sent to the Recycle Bin.",
                        TargetWeb.Url,
                        entity.ListName);

                return ProcessStatus.Invalid;
            }

            Guid[] deletedGuids = this.GetProperty<Guid[]>(TargetWeb, DeletedListPropName);

            if (deletedGuids == null)
            {
                TraceHelper.TraceVerbose(TraceSwitch,
                    "DeleteList",
                    "Cannot find Ids of the deleted list items for list '{0}' in web '{1}'",
                    entity.ListName, TargetWeb.Url);

                return ProcessStatus.Invalid;
            }

            for (int i = 0; i < deletedGuids.Length; i++)
            {
                Guid currentListItemGuid = deletedGuids[i];

                if (deletedGuids[0] == Guid.Empty)
                {
                    this.Trace.TraceWarning(
                            "This object {0} cannot be restored in this web {1} - as the Guid cannot be determined.",
                            TargetWeb.Url,
                            entity.ListName);

                    return ProcessStatus.Invalid;
                }

                // Attempt to restore
                this.Trace.TraceVerbose(
                        "Restoring this object {0}('{2}') to this web {1}",
                        TargetWeb.Url,
                        entity.ListName,
                        deletedGuids[0].ToString());

                SPListHelper.RestoreFromRecycleBin(TargetWeb, deletedGuids[i]);
            }

            return ProcessStatus.Success;
        }

        private ProcessStatus ProcessDo(SafContext context, ListToDelete entity)
        {
            Guid listToDeleteGuid = SPListHelper.GetListGuid(TargetWeb, entity.ListName);

            if (listToDeleteGuid == Guid.Empty)
            {
                this.Trace.TraceVerbose(
                        "The list {0} doesn't exist in this web {1}", entity.ListName, TargetWeb.Url);

                return ProcessStatus.Invalid;
            }
            
            // Do we Recycle or permanently delete ?
            if (entity.Destroy.Value)
            {
                this.Trace.TraceVerbose(
                        "Attempting to delete this list {0} in this web {1}",
                        entity.ListName,
                        TargetWeb.Url);

                SPListHelper.DeleteList(TargetWeb, entity.ListName, entity.ListItemsOnly.Value);
            }
            else
            {
                this.Trace.TraceVerbose(
                        "Attempting to recycle this list {0} in this web {1}",
                        entity.ListName,
                        TargetWeb.Url);

                Guid[] recycledGuids = SPListHelper.RecycleList(TargetWeb, entity.ListName, entity.ListItemsOnly.Value);
                    
                this.SaveProperty<Guid[]>(TargetWeb, DeletedListPropName, recycledGuids);                
            }

            return ProcessStatus.Success;
        }

        /// <summary>
        /// Checks the Data entity for Validity
        /// </summary>
        /// <param name="context">The <see cref="IContext"/>context.</param>
        /// <param name="entity">The data entity to Validate</param>
        /// <param name="errors">List of <see cref="ValidationError"/>s</param>
        /// <param name="mode"><see cref="ProcessMode"/> signalling wheter we are Doing, or Undoing the action.</param>
        /// <returns>false if invalid</returns>
        protected override bool IsValid(SafContext context, ListToDelete entity, ref List<ValidationError> errors, ProcessMode mode)
        {
            int currentCount = errors.Count;

            // Validate each object now.
            ValidateStringForNull(entity.ListName, "entity.ListName", ref errors);
            ValidateNullable(entity.ListItemsOnly, "entity.ListItemsOnly", ref errors);

            if (!entity.Destroy.HasValue)
                entity.Destroy = false;

            // Have we added errors ?
            return errors.Count == currentCount;
        }
    }
}